/*
 * DalvikMain.c
 *
 *  Created on: 2011-8-2
 *      Author: gexiao
 */
/*
 * Command-line invocation of the Dalvik VM.
 */
#include "DalvikMain.h"
#include "../libnativehelper/include/nativehelper/jni.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <assert.h>

/*
 * We want failed write() calls to just return with an error.
 */
static void blockSigpipe() {
	sigset_t mask;

	sigemptyset(&mask);
	sigaddset(&mask, SIGPIPE);
	if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
		fprintf(stderr, "WARNING: SIGPIPE not blocked\n");
}

/*
 * Parse arguments. Most of it just gets passed through to the VM. The
 * JNI spec defines a handful of standard arguments.
 */
int dalvikMain(int argc, char* const argv[]) {
	JavaVM* vm = NULL;
	JNIEnv* env = NULL;
	JavaVMInitArgs initArgs;
	JavaVMOption* options = NULL;
	char* slashClass = NULL;
	int optionCount, curOpt, i, argIdx;
	int needExtra = JNI_FALSE;
	int result = 1;

	fprintf(stdout, "Dalvik VM starting\n");

	setvbuf(stdout, NULL, _IONBF, 0);

	//ignore argv[0]
	argv++;
	argc--;

	/*
	 * If we're adding any additional stuff, e.g. function hook specifiers,
	 * add them to the count here.
	 *
	 * We're over-allocating, because this includes the options to the VM
	 * plus the options to the program.
	 */
	optionCount = argc;

	options = (JavaVMOption*) malloc(sizeof(JavaVMOption) * optionCount);
	memset(options,0,sizeof(JavaVMOption)*optionCount);

	/*
	 * Copy options over. Everything up to the name of the class starts
	 * with a '-' (the function hook stuff is strictly internal).
	 */
	for (curOpt = argIdx = 0; argIdx < argc; argIdx++) {
		if (argv[argIdx][0] != '-' && !needExtra)
			break;
		options[curOpt++].optionString = strdup(argv[argIdx]);

		/* some options require an additional arg */
		needExtra = JNI_FALSE;
		if (strcmp(argv[argIdx], "-classpath") == 0 || strcmp(argv[argIdx],
				"-cp") == 0)
		/* others? */
		{
			needExtra = JNI_TRUE;
		}
	}

	if (needExtra) {
		fprintf(stderr, "Dalvik VM requires value after last option flag\n");
		goto bail;
	}

	/* insert additional internal options here */

	assert(curOpt <= optionCount);

	initArgs.version = JNI_VERSION_1_4;
	initArgs.options = options;
	initArgs.nOptions = curOpt;
	initArgs.ignoreUnrecognized = JNI_FALSE;

	blockSigpipe();

	/*
	 * Start VM.  The current thread becomes the main thread of the VM.
	 */
	if (JNI_CreateJavaVM(&vm, &env, &initArgs) < 0) {
		fprintf(stderr, "Dalvik VM init failed (check log file)\n");
		goto bail;
	}

	bail:
	//some code here
	return result;
}
